import os
import json
import time
import logging
from typing import Dict, Any, List
from .base_processor import BaseProcessor
from prompts import (
    PROMPT_EVALUATION_SINGLE_SYSTEM, PROMPT_EVALUATION_SINGLE_USER,
    PROMPT_EVALUATION_HORIZONTAL_SYSTEM, PROMPT_EVALUATION_HORIZONTAL_USER,
    PROMPT_EVALUATION_MATRIX_SYSTEM, PROMPT_EVALUATION_MATRIX_USER,
    PROMPT_EVALUATION_GUIDE_SYSTEM, PROMPT_EVALUATION_GUIDE_USER
)

# 获取当前模块的日志记录器
from app.utils.logger import get_logger

# 传入当前模块名，获取已配置好的日志器
logger = get_logger(__name__)


class EvaluationProcessor(BaseProcessor):
    """测评类处理器（全参数匹配Prompt占位符）"""

    def __init__(self, volcano_client, additional_info=""):
        super().__init__(volcano_client)
        self.additional_info = additional_info  # 预留参数（若后续Prompt需要可启用）
        logger.info(f"🎬 EvaluationProcessor初始化完成，附加信息: {additional_info}")

    async def process(self, inputs: Dict[str, Any]) -> List[Dict[str, str]]:
        """处理测评类任务"""
        logger.info("🚀 开始处理测评任务")
        process_start = time.time()

        # 1. 提取所有参数（与Prompt占位符一一对应，确保无遗漏）
        # 从inputs中提取，键名与content_service传入的evaluation_inputs一致
        product_name = inputs.get("product_name", "")  # 匹配{product_name}
        video_outline = inputs.get("outline", "")      # 匹配{video_outline}
        notice = inputs.get("notice", "")              # 匹配{notice}
        ProductHighlights = inputs.get("ProductHighlights", {})  # 匹配{ProductHighlights}
        expert_style = inputs.get("expert_style", {})  # 匹配{expert_style}
        outline_advice = inputs.get("outline_advice", "")  # 匹配{outline_advice}
        direction = inputs.get("direction", "")

        # 记录关键输入参数
        logger.info(f"📋 输入参数解析完成 - 测评方向: {direction}")
        logger.info(f"🏷️ 产品名称: {product_name}")
        logger.info(f"📝 视频大纲长度: {len(video_outline)} 字符")
        logger.info(f"🎯 产品亮点数量: {len(ProductHighlights) if isinstance(ProductHighlights, dict) else '非字典类型'}")
        logger.debug(f"专家风格键值: {list(expert_style.keys()) if expert_style else '空'}")
        logger.debug(f"大纲建议: {outline_advice[:100] if outline_advice else '无'}")

        # 输入验证日志
        if not product_name:
            logger.warning("⚠️ 产品名称为空，可能会影响生成质量")
        if not video_outline:
            logger.warning("⚠️ 视频大纲为空，可能会影响生成质量")

        logger.info("🔄 开始调用模型处理...")

        # 3. 调用模型时传递所有参数（与Prompt占位符完全对应）
        result = await self.select_and_call_model(
            direction=direction,
            product_name=product_name,
            video_outline=video_outline,
            notice=notice,
            ProductHighlights=ProductHighlights,
            expert_style=expert_style,
            outline_advice=outline_advice
        )

        # 记录处理结果
        process_time = time.time() - process_start
        logger.info(f"✅ 测评任务处理完成 - 方向: {direction}, 总耗时: {process_time:.2f}s")

        # 解析JSON响应
        logger.info("🔄 开始解析模型响应JSON")
        parsed_result = self.parse_json_response(result)

        if parsed_result and not (len(parsed_result) == 1 and "error" in parsed_result[0]):
            logger.info("✅ JSON解析成功")
            logger.debug(f"解析结果数量: {len(parsed_result)}")
        else:
            logger.error(f"❌ JSON解析失败或返回错误")
            logger.debug(f"原始响应内容: {result}")

        return parsed_result

    async def select_and_call_model(
        self, direction, product_name, video_outline, notice,
        ProductHighlights, expert_style, outline_advice
    ):
        """
        全参数匹配：确保每个Prompt的占位符都有对应的参数传递
        所有测评类Prompt的占位符统一为：
        {product_name}、{video_outline}、{notice}、{ProductHighlights}、{expert_style}、{outline_advice}
        """
        logger.info(f"🎯 选择模型处理方向: {direction}")
        select_start = time.time()

        try:
            # 序列化复杂参数（处理dict/list类型，避免格式化错误）
            highlights_str = json.dumps(ProductHighlights, ensure_ascii=False) if isinstance(ProductHighlights, (dict, list)) else str(ProductHighlights)
            style_str = json.dumps(expert_style, ensure_ascii=False) if isinstance(expert_style, (dict, list)) else str(expert_style)

            # 记录提示词构建信息
            logger.debug(f"构建提示词 - 产品名称: {product_name}")
            logger.debug(f"构建提示词 - 视频大纲长度: {len(video_outline)}")
            logger.debug(f"构建提示词 - 产品亮点长度: {len(highlights_str)}")
            logger.debug(f"构建提示词 - 专家风格长度: {len(style_str)}")

            model_response = None

            # 1. 单品测评（全参数匹配）
            if direction == "单品测评":
                logger.info("📹 处理单品测评")
                user_prompt = PROMPT_EVALUATION_SINGLE_USER.format(
                    product_name=product_name,
                    video_outline=video_outline,
                    notice=notice,
                    ProductHighlights=highlights_str,
                    expert_style=style_str,
                    outline_advice=outline_advice
                )
                logger.debug(f"单品测评提示词长度: {len(user_prompt)}")
                model_response = await self.call_model(
                    system_prompt=PROMPT_EVALUATION_SINGLE_SYSTEM,
                    user_prompt=user_prompt
                )

            # 2. 横向测评（全参数匹配）
            elif direction == "横向测评":
                logger.info("🔄 处理横向测评")
                user_prompt = PROMPT_EVALUATION_HORIZONTAL_USER.format(
                    product_name=product_name,
                    video_outline=video_outline,
                    notice=notice,
                    ProductHighlights=highlights_str,
                    expert_style=style_str,
                    outline_advice=outline_advice
                )
                logger.debug(f"横向测评提示词长度: {len(user_prompt)}")
                model_response = await self.call_model(
                    system_prompt=PROMPT_EVALUATION_HORIZONTAL_SYSTEM,
                    user_prompt=user_prompt
                )

            # 3. 同品牌矩阵测评（全参数匹配）
            elif direction == "同品牌矩阵测评":
                logger.info("🏢 处理同品牌矩阵测评")
                user_prompt = PROMPT_EVALUATION_MATRIX_USER.format(
                    product_name=product_name,
                    video_outline=video_outline,
                    notice=notice,
                    ProductHighlights=highlights_str,
                    expert_style=style_str,
                    outline_advice=outline_advice
                )
                logger.debug(f"同品牌矩阵测评提示词长度: {len(user_prompt)}")
                model_response = await self.call_model(
                    system_prompt=PROMPT_EVALUATION_MATRIX_SYSTEM,
                    user_prompt=user_prompt
                )

            # 4. 选购指南测评（全参数匹配）
            elif direction == "选购指南测评":
                logger.info("📚 处理选购指南测评")
                user_prompt = PROMPT_EVALUATION_GUIDE_USER.format(
                    product_name=product_name,
                    video_outline=video_outline,
                    notice=notice,
                    ProductHighlights=highlights_str,
                    expert_style=style_str,
                    outline_advice=outline_advice
                )
                logger.debug(f"选购指南测评提示词长度: {len(user_prompt)}")
                model_response = await self.call_model(
                    system_prompt=PROMPT_EVALUATION_GUIDE_SYSTEM,
                    user_prompt=user_prompt
                )

            # 未知方向兜底
            else:
                error_msg = f"未支持的测评方向：{direction}，仅支持【单品测评/横向测评/同品牌矩阵测评/选购指南测评】"
                logger.error(f"❌ {error_msg}")
                model_response = json.dumps({
                    "error_type": "未知方向",
                    "error_msg": error_msg,
                    "supported_directions": ["单品测评", "横向测评", "同品牌矩阵测评", "选购指南测评"]
                }, ensure_ascii=False)

            # 记录模型响应信息
            if model_response and not model_response.startswith('{"error_type"'):
                logger.info(f"🤖 模型调用成功，响应长度: {len(model_response)}")
                logger.debug(f"模型响应前500字符: {model_response[:500]}...")
            elif model_response:
                logger.warning(f"⚠️ 模型返回错误响应: {model_response}")

        # 异常捕获（覆盖所有可能的错误）
        except json.JSONDecodeError as e:
            error_msg = f"参数序列化失败：{str(e)}（检查ProductHighlights或expert_style格式）"
            logger.error(f"💥 {error_msg}", exc_info=True)
            model_response = json.dumps({
                "error_type": "JSON序列化错误",
                "error_msg": error_msg
            }, ensure_ascii=False)
        except KeyError as e:
            error_msg = f"Prompt占位符与参数不匹配：缺少{str(e)}（检查参数传递是否完整）"
            logger.error(f"💥 {error_msg}", exc_info=True)
            model_response = json.dumps({
                "error_type": "参数匹配错误",
                "error_msg": error_msg
            }, ensure_ascii=False)
        except Exception as e:
            error_msg = f"模型调用异常：{str(e)}"
            logger.error(f"💥 {error_msg}", exc_info=True)
            model_response = json.dumps({
                "error_type": "模型调用失败",
                "error_msg": error_msg
            }, ensure_ascii=False)

        logger.debug(f"测评方向匹配+模型调用总耗时: {time.time() - select_start:.2f}s")
        return model_response

    def parse_json_response(self, response: str) -> List[Dict[str, str]]:
        """解析分镜列表，增强容错性"""
        logger.info("🔄 开始解析分镜列表JSON响应")
        try:
            fixed_response = response.strip()
            # 处理多JSON块拼接的情况
            if fixed_response.startswith("[{") and fixed_response.endswith("}]"):
                fixed_response = fixed_response.replace("]\n[", "],[")
                if not fixed_response.startswith("["):
                    fixed_response = "[" + fixed_response
                if not fixed_response.endswith("]"):
                    fixed_response = fixed_response + "]"

            parsed = json.loads(fixed_response)

            # 提取分镜列表
            if isinstance(parsed, list):
                logger.info(f"✅ 成功解析分镜列表，包含 {len(parsed)} 个分镜")
                return parsed
            if isinstance(parsed, dict):
                for key in ["分镜脚本", "shot_list", "shots", "分镜"]:
                    if key in parsed and isinstance(parsed[key], list):
                        logger.info(f"✅ 成功从字段'{key}'解析分镜列表，包含 {len(parsed[key])} 个分镜")
                        return parsed[key]
                # 单个分镜转为列表
                if all(field in parsed for field in ["镜号", "景别", "画面", "口播"]):
                    logger.info("✅ 成功解析单个分镜并转为列表")
                    return [parsed]

            logger.warning(f"⚠️ 分镜格式不符合预期: {response[:100]}...")
            return []
        except json.JSONDecodeError as e:
            logger.error(f"❌ 分镜解析失败: {str(e)}, 原始数据: {response[:100]}...")
            return [{"error": f"解析失败: {str(e)}"}]